package com.example.demo.common.r2dbc;

import org.springframework.data.r2dbc.core.R2dbcEntityTemplate;
import org.springframework.transaction.annotation.Transactional;
import reactor.util.Logger;
import reactor.util.Loggers;
import org.reactivestreams.Publisher;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.data.repository.NoRepositoryBean;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.util.List;
import java.util.function.Function;

/**
 * 基本服务
 * @param <M>
 * @param <T>
 * @param <ID>
 */
@NoRepositoryBean
public class BaseServiceImpl<M extends BaseRepository<T, ID>, T, ID> implements BaseService<T, ID>{

    protected Logger log = Loggers.getLogger(this.getClass());

    @Autowired
    protected M baseRepository;

    @Autowired
    protected R2dbcEntityTemplate template;

    @Override
    @Transactional
    public <S extends T> Mono<S> save(S entity) {
        return baseRepository.save(entity);
    }

    @Override
    @Transactional
    public <S extends T> Flux<S> saveAll(Iterable<S> entitys) {
        return baseRepository.saveAll(entitys);
    }

    @Override
    @Transactional
    public <S extends T> Flux<S> saveAll(Publisher<S> entitys) {
        return baseRepository.saveAll(entitys);
    }

    @Override
    public Mono<T> findById(ID id) {
        return baseRepository.findById(id);
    }

    @Override
    public Mono<T> findById(Publisher<ID> id) {
        return baseRepository.findById(id);
    }

    @Override
    public Mono<Boolean> existsById(ID id) {
        return baseRepository.existsById(id);
    }

    @Override
    public Mono<Boolean> existsById(Publisher<ID> id) {
        return baseRepository.existsById(id);
    }

    @Override
    public Flux<T> findAll() {
        return baseRepository.findAll();
    }

    @Override
    public Mono<Page<T>> findAllPage(Pageable pageable) {
        return baseRepository.findListWithPage(pageable)
                .collectList()
                .transform( f -> {
                    return Mono.just(new PageImpl<T>(f.block(), pageable, count().block()));
                });
    }

    @Override
    public Flux<T> findAllById(Iterable<ID> ids) {
        return baseRepository.findAllById(ids);
    }

    @Override
    public Flux<T> findAllById(Publisher<ID> ids) {
        return baseRepository.findAllById(ids);
    }

    @Override
    public Mono<Long> count() {
        return baseRepository.count();
    }

    @Override
    @Transactional
    public Mono<Void> deleteById(ID id) {
        return baseRepository.deleteById(id);
    }

    @Override
    @Transactional
    public Mono<Void> deleteById(Publisher<ID> id) {
        return baseRepository.deleteById(id);
    }

    @Override
    @Transactional
    public Mono<Void> delete(T entity) {
        return baseRepository.delete(entity);
    }

    @Override
    @Transactional
    public Mono<Void> deleteAll(Iterable<? extends T> entitys) {
        return baseRepository.deleteAll(entitys);
    }

    @Override
    @Transactional
    public Mono<Void> deleteAll(Publisher<? extends T> entitys) {
        return baseRepository.deleteAll(entitys);
    }

    @Override
    @Transactional
    public Mono<Void> deleteAll() {
        return baseRepository.deleteAll();
    }

}
